//! 配置管理模块
//! 
//! 提供数据生成配置和数据库配置管理

use crate::error::{DataForgeError, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::Path;


/// 事务模式
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum TransactionMode {
    /// 自动提交
    AutoCommit,
    /// 手动提交
    Manual,
    /// 批量提交
    Batch { batch_size: usize },
}

impl Default for TransactionMode {
    fn default() -> Self {
        Self::Batch { batch_size: 1000 }
    }
}

/// 数据库配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseConfig {
    /// 数据库URL
    pub url: String,
    /// 最大连接数
    pub max_connections: u32,
    /// 连接超时时间（秒）
    pub connection_timeout: u64,
    /// 最大重试次数
    pub max_retries: u32,
    /// 批量插入大小
    pub batch_insert_size: usize,
    /// 事务模式
    pub transaction_mode: TransactionMode,
    /// 连接池配置
    pub pool_config: PoolConfig,
    /// SSL配置
    pub ssl_config: Option<SslConfig>,
}

/// 连接池配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PoolConfig {
    /// 最小连接数
    pub min_connections: u32,
    /// 最大连接数
    pub max_connections: u32,
    /// 连接空闲超时时间（秒）
    pub idle_timeout: u64,
    /// 连接最大生存时间（秒）
    pub max_lifetime: u64,
}

/// SSL配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SslConfig {
    /// 是否启用SSL
    pub enabled: bool,
    /// CA证书路径
    pub ca_cert_path: Option<String>,
    /// 客户端证书路径
    pub client_cert_path: Option<String>,
    /// 客户端私钥路径
    pub client_key_path: Option<String>,
    /// 是否验证服务器证书
    pub verify_server_cert: bool,
}

/// 生成器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeneratorConfig {
    /// 生成器名称
    pub name: String,
    /// 生成器类型
    pub generator_type: String,
    /// 配置参数
    pub params: HashMap<String, serde_json::Value>,
    /// 权重（用于随机选择）
    pub weight: f64,
    /// 是否启用
    pub enabled: bool,
}

/// 数据生成配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataGenConfig {
    /// 每批次生成数量
    pub batch_size: usize,
    /// 区域设置
    pub locale: String,
    /// 空值概率 (0.0-1.0)
    pub null_probability: f32,
    /// 并行度 (0表示自动检测)
    pub parallelism: usize,
    /// 生成策略
    pub strategy: String,
    /// 输出格式
    pub output_format: OutputFormat,
    /// 字段配置
    pub fields: HashMap<String, FieldConfig>,
    /// 全局生成器配置
    pub generators: Vec<GeneratorConfig>,
    /// 内存配置
    pub memory_config: MemoryConfig,
}

/// 输出格式
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OutputFormat {
    Json,
    Csv,
    Sql,
    Parquet,
    Avro,
}

/// 字段配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldConfig {
    /// 字段名
    pub name: String,
    /// 数据类型
    pub data_type: String,
    /// 生成器名称
    pub generator: String,
    /// 生成器参数
    pub generator_params: HashMap<String, serde_json::Value>,
    /// 约束条件
    pub constraints: ConstraintConfig,
    /// 是否可为空
    pub nullable: bool,
    /// 默认值
    pub default_value: Option<serde_json::Value>,
}

/// 约束配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConstraintConfig {
    /// 最小值
    pub min: Option<serde_json::Value>,
    /// 最大值
    pub max: Option<serde_json::Value>,
    /// 正则表达式
    pub pattern: Option<String>,
    /// 枚举值
    pub enum_values: Option<Vec<serde_json::Value>>,
    /// 长度限制
    pub length: Option<LengthConstraint>,
    /// 唯一性约束
    pub unique: bool,
}

/// 长度约束
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LengthConstraint {
    /// 最小长度
    pub min: Option<usize>,
    /// 最大长度
    pub max: Option<usize>,
}

/// 内存配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryConfig {
    /// 内存池初始大小
    pub pool_initial_size: usize,
    /// 内存池最大大小
    pub pool_max_size: usize,
    /// 字符串池大小
    pub string_pool_size: usize,
    /// 清理间隔（秒）
    pub cleanup_interval: u64,
    /// 最大空闲时间（秒）
    pub max_idle_time: u64,
}

/// 主配置结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    /// 应用配置
    pub app: AppConfig,
    /// 数据生成配置
    pub data_generation: DataGenConfig,
    /// 数据库配置
    pub databases: HashMap<String, DatabaseConfig>,
    /// 日志配置
    pub logging: LoggingConfig,
    /// 监控配置
    pub monitoring: MonitoringConfig,
}

/// 应用配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
    /// 应用名称
    pub name: String,
    /// 版本
    pub version: String,
    /// 环境
    pub environment: String,
    /// 调试模式
    pub debug: bool,
    /// 工作目录
    pub work_dir: String,
}

/// 日志配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoggingConfig {
    /// 日志级别
    pub level: String,
    /// 日志格式
    pub format: String,
    /// 输出目标
    pub targets: Vec<LogTarget>,
}

/// 日志目标
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogTarget {
    /// 目标类型
    pub target_type: String,
    /// 配置参数
    pub config: HashMap<String, serde_json::Value>,
}

/// 监控配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitoringConfig {
    /// 是否启用监控
    pub enabled: bool,
    /// 指标收集间隔（秒）
    pub metrics_interval: u64,
    /// Prometheus配置
    pub prometheus: Option<PrometheusConfig>,
    /// 健康检查配置
    pub health_check: HealthCheckConfig,
}

/// Prometheus配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrometheusConfig {
    /// 监听地址
    pub listen_address: String,
    /// 监听端口
    pub port: u16,
    /// 指标路径
    pub metrics_path: String,
}

/// 健康检查配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheckConfig {
    /// 是否启用
    pub enabled: bool,
    /// 检查间隔（秒）
    pub interval: u64,
    /// 超时时间（秒）
    pub timeout: u64,
}

/// 配置管理器
pub struct ConfigManager {
    config: Config,
    config_path: Option<String>,
}

impl ConfigManager {
    /// 创建新的配置管理器
    pub fn new(config: Config) -> Self {
        Self {
            config,
            config_path: None,
        }
    }

    /// 从文件加载配置
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
        let path_str = path.as_ref().to_string_lossy().to_string();
        let content = std::fs::read_to_string(&path)
            .map_err(|e| DataForgeError::config(&format!("Failed to read config file: {}", e)))?;

        let config = if path_str.ends_with(".toml") {
            toml::from_str(&content)
                .map_err(|e| DataForgeError::config(&format!("Failed to parse TOML config: {}", e)))?
        } else if path_str.ends_with(".yaml") || path_str.ends_with(".yml") {
            serde_yaml::from_str(&content)
                .map_err(|e| DataForgeError::config(&format!("Failed to parse YAML config: {}", e)))?
        } else if path_str.ends_with(".json") {
            serde_json::from_str(&content)
                .map_err(|e| DataForgeError::config(&format!("Failed to parse JSON config: {}", e)))?
        } else {
            return Err(DataForgeError::config("Unsupported config file format"));
        };

        Ok(Self {
            config,
            config_path: Some(path_str),
        })
    }

    /// 创建默认配置
    pub fn default() -> Self {
        Self {
            config: Config::default(),
            config_path: None,
        }
    }

    /// 获取配置
    pub fn config(&self) -> &Config {
        &self.config
    }

    /// 获取可变配置
    pub fn config_mut(&mut self) -> &mut Config {
        &mut self.config
    }

    /// 保存配置到文件
    pub fn save(&self) -> Result<()> {
        if let Some(path) = &self.config_path {
            let content = if path.ends_with(".toml") {
                toml::to_string_pretty(&self.config)
                    .map_err(|e| DataForgeError::config(&format!("Failed to serialize TOML config: {}", e)))?
            } else if path.ends_with(".yaml") || path.ends_with(".yml") {
                serde_yaml::to_string(&self.config)
                    .map_err(|e| DataForgeError::config(&format!("Failed to serialize YAML config: {}", e)))?
            } else if path.ends_with(".json") {
                serde_json::to_string_pretty(&self.config)
                    .map_err(|e| DataForgeError::config(&format!("Failed to serialize JSON config: {}", e)))?
            } else {
                return Err(DataForgeError::config("Unsupported config file format"));
            };

            std::fs::write(path, content)
                .map_err(|e| DataForgeError::config(&format!("Failed to write config file: {}", e)))?;
        } else {
            return Err(DataForgeError::config("No config file path specified"));
        }

        Ok(())
    }

    /// 验证配置
    pub fn validate(&self) -> Result<()> {
        let config = &self.config;

        // 验证数据生成配置
        if config.data_generation.batch_size == 0 {
            return Err(DataForgeError::config("Batch size must be greater than 0"));
        }

        if config.data_generation.null_probability < 0.0 || config.data_generation.null_probability > 1.0 {
            return Err(DataForgeError::config("Null probability must be between 0.0 and 1.0"));
        }

        // 验证数据库配置
        for (name, db_config) in &config.databases {
            if db_config.url.is_empty() {
                return Err(DataForgeError::config(&format!("Database '{}' URL cannot be empty", name)));
            }

            if db_config.max_connections == 0 {
                return Err(DataForgeError::config(&format!("Database '{}' max_connections must be greater than 0", name)));
            }

            if db_config.batch_insert_size == 0 {
                return Err(DataForgeError::config(&format!("Database '{}' batch_insert_size must be greater than 0", name)));
            }
        }

        // 验证内存配置
        let mem_config = &config.data_generation.memory_config;
        if mem_config.pool_max_size < mem_config.pool_initial_size {
            return Err(DataForgeError::config("Memory pool max_size must be >= initial_size"));
        }

        Ok(())
    }

    /// 合并配置
    pub fn merge(&mut self, other: Config) -> Result<()> {
        // 简单的合并逻辑，实际应用中可能需要更复杂的合并策略
        self.config.data_generation.batch_size = other.data_generation.batch_size;
        self.config.data_generation.null_probability = other.data_generation.null_probability;
        
        // 合并数据库配置
        for (name, db_config) in other.databases {
            self.config.databases.insert(name, db_config);
        }

        // 合并字段配置
        for (name, field_config) in other.data_generation.fields {
            self.config.data_generation.fields.insert(name, field_config);
        }

        self.validate()
    }

    /// 获取数据库配置
    pub fn get_database_config(&self, name: &str) -> Option<&DatabaseConfig> {
        self.config.databases.get(name)
    }

    /// 获取字段配置
    pub fn get_field_config(&self, name: &str) -> Option<&FieldConfig> {
        self.config.data_generation.fields.get(name)
    }

    /// 设置环境变量覆盖
    pub fn apply_env_overrides(&mut self) {
        // 从环境变量覆盖配置
        if let Ok(batch_size) = std::env::var("DATAFORGE_BATCH_SIZE") {
            if let Ok(size) = batch_size.parse::<usize>() {
                self.config.data_generation.batch_size = size;
            }
        }

        if let Ok(null_prob) = std::env::var("DATAFORGE_NULL_PROBABILITY") {
            if let Ok(prob) = null_prob.parse::<f32>() {
                self.config.data_generation.null_probability = prob;
            }
        }

        if let Ok(parallelism) = std::env::var("DATAFORGE_PARALLELISM") {
            if let Ok(par) = parallelism.parse::<usize>() {
                self.config.data_generation.parallelism = par;
            }
        }
    }
}

// 默认实现
impl Default for Config {
    fn default() -> Self {
        Self {
            app: AppConfig {
                name: "DataForge".to_string(),
                version: "0.1.0".to_string(),
                environment: "development".to_string(),
                debug: true,
                work_dir: ".".to_string(),
            },
            data_generation: DataGenConfig {
                batch_size: 1000,
                locale: "zh_CN".to_string(),
                null_probability: 0.05,
                parallelism: 0,
                strategy: "random".to_string(),
                output_format: OutputFormat::Json,
                fields: HashMap::new(),
                generators: Vec::new(),
                memory_config: MemoryConfig {
                    pool_initial_size: 10,
                    pool_max_size: 1000,
                    string_pool_size: 1000,
                    cleanup_interval: 60,
                    max_idle_time: 300,
                },
            },
            databases: HashMap::new(),
            logging: LoggingConfig {
                level: "info".to_string(),
                format: "json".to_string(),
                targets: vec![LogTarget {
                    target_type: "console".to_string(),
                    config: HashMap::new(),
                }],
            },
            monitoring: MonitoringConfig {
                enabled: false,
                metrics_interval: 30,
                prometheus: None,
                health_check: HealthCheckConfig {
                    enabled: true,
                    interval: 30,
                    timeout: 5,
                },
            },
        }
    }
}

impl Default for DatabaseConfig {
    fn default() -> Self {
        Self {
            url: "sqlite::memory:".to_string(),
            max_connections: 10,
            connection_timeout: 30,
            max_retries: 3,
            batch_insert_size: 1000,
            transaction_mode: TransactionMode::default(),
            pool_config: PoolConfig {
                min_connections: 1,
                max_connections: 10,
                idle_timeout: 600,
                max_lifetime: 3600,
            },
            ssl_config: None,
        }
    }
}

impl Default for ConstraintConfig {
    fn default() -> Self {
        Self {
            min: None,
            max: None,
            pattern: None,
            enum_values: None,
            length: None,
            unique: false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;


    #[test]
    fn test_default_config() {
        let config = Config::default();
        assert_eq!(config.app.name, "DataForge");
        assert_eq!(config.data_generation.batch_size, 1000);
        assert_eq!(config.data_generation.null_probability, 0.05);
    }

    #[test]
    fn test_config_validation() {
        let manager = ConfigManager::default();
        assert!(manager.validate().is_ok());

        let mut invalid_config = Config::default();
        invalid_config.data_generation.batch_size = 0;
        let invalid_manager = ConfigManager {
            config: invalid_config,
            config_path: None,
        };
        assert!(invalid_manager.validate().is_err());
    }

    #[test]
    fn test_config_serialization() {
        let config = Config::default();
        
        // 测试JSON序列化
        let json_str = serde_json::to_string_pretty(&config).unwrap();
        let deserialized: Config = serde_json::from_str(&json_str).unwrap();
        assert_eq!(config.app.name, deserialized.app.name);
    }

    #[test]
    fn test_env_overrides() {
        std::env::set_var("DATAFORGE_BATCH_SIZE", "2000");
        std::env::set_var("DATAFORGE_NULL_PROBABILITY", "0.1");
        
        let mut manager = ConfigManager::default();
        manager.apply_env_overrides();
        
        assert_eq!(manager.config.data_generation.batch_size, 2000);
        assert_eq!(manager.config.data_generation.null_probability, 0.1);
        
        // 清理环境变量
        std::env::remove_var("DATAFORGE_BATCH_SIZE");
        std::env::remove_var("DATAFORGE_NULL_PROBABILITY");
    }

    #[test]
    fn test_database_config() {
        let mut config = Config::default();
        let db_config = DatabaseConfig {
            url: "mysql://user:pass@localhost/test".to_string(),
            max_connections: 20,
            ..Default::default()
        };
        
        config.databases.insert("test_db".to_string(), db_config);
        
        let manager = ConfigManager {
            config,
            config_path: None,
        };
        
        let db_config = manager.get_database_config("test_db").unwrap();
        assert_eq!(db_config.url, "mysql://user:pass@localhost/test");
        assert_eq!(db_config.max_connections, 20);
    }
}